package com.small.site.security;

import com.small.site.cache.CacheService;
import com.small.site.constant.Constant;
import com.small.site.enums.ResponseCode;
import com.small.site.exception.Assert;
import com.small.site.pojo.SysPermission;
import com.small.site.pojo.SysUser;
import com.small.site.service.PermissionService;
import com.small.site.service.UserService;
import com.small.site.vo.UserDetailsVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author xiaochi
 * @date 2021/12/11 17:06
 * @desc 登录账号信息获取
 */
@Slf4j
@SuppressWarnings("all")
public class LoginUserDetailsService implements UserDetailsService {

    @Autowired
    private CacheService cacheService;
    @Autowired
    private UserService userService;
    @Autowired
    private PermissionService permissionService;

    /**
     * 账号信息获取
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String userKey = this.getEntryCacheKey(username);
        String permissionKey = this.getPermissionCacheKey(username);
        SysUser sysUser = cacheService.getEntityCache(userKey, Constant.User.USER_KEY_EXPIRE, SysUser.class, () -> userService.getUserByUserName(username));
        Assert.isTure(Objects.nonNull(sysUser),new UsernameNotFoundException(ResponseCode.SYSTEM_PASSWORD_ERROR.getMessage()));
        List<SysPermission> permissionList = cacheService.getListCache(permissionKey, Constant.User.USER_KEY_EXPIRE, SysPermission.class, () -> permissionService.permissionListByUserId(sysUser.getId()));
        UserDetailsVo userDetailsVo = new UserDetailsVo();
        BeanUtils.copyProperties(sysUser,userDetailsVo);
        return this.getUserDetails(userDetailsVo,permissionList);
    }

    /**
     * 获取用户与设置权限数据
     * @param userDetailsVo
     * @param permissionList
     * @return
     */
    public UserDetails getUserDetails(UserDetailsVo userDetailsVo, List<SysPermission> permissionList) {
        userDetailsVo.setMenus(permissionService.permissionTreeListMenu(permissionList));
        userDetailsVo.setPermissions(permissionList.stream().filter(x -> StringUtils.isNotBlank(x.getCode())).map(x -> x.getCode()).distinct().collect(Collectors.toList()));
        List<String> permsList = permissionList.stream().filter(x -> StringUtils.isNotBlank(x.getPerms())).map(x -> x.getPerms()).distinct().collect(Collectors.toList());
        String[] perms = permsList.toArray(new String[0]);
        userDetailsVo.setAuthorities(AuthorityUtils.createAuthorityList(perms));
        return userDetailsVo;
    }

    public String getEntryCacheKey(String username) {
        return Constant.User.USER_KEY + this.obtainUsername(username);
    }

    public String getPermissionCacheKey(String username){
        return Constant.User.PERMISSION_KEY + this.obtainUsername(username);
    }

    private String obtainUsername(String username){
        return username == null || "".equals(username) ? "" : username;
    }
}
